home *** CD-ROM | disk | FTP | other *** search
/ Cream of the Crop 22 / Cream of the Crop 22.iso / windows / wdj1096.zip / BURK.ZIP / BENCH.CPP next >
C/C++ Source or Header  |  1996-08-02  |  24KB  |  689 lines

  1. // modified by Ron Burk to parameterize the data type
  2. // being used in the benchmarks.
  3.  
  4. //typedef int DATA;
  5. typedef double DATA;
  6.  
  7. //=============================================================================
  8. //
  9. //  OOPACK - a benchmark for comparing OOP vs. C-style programming.
  10. //  Copyright (C) 1995 Arch D. Robison
  11. //
  12. //  This program is free software; you can redistribute it and/or modify
  13. //  it under the terms of the GNU General Public License as published by
  14. //  the Free Software Foundation; either version 2 of the License, or
  15. //  (at your option) any later version.
  16. //
  17. //  This program is distributed in the hope that it will be useful,
  18. //  but WITHOUT ANY WARRANTY; without even the implied warranty of
  19. //  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  20. //  GNU General Public License for more details.
  21. //
  22. //  For a copy of the GNU General Public License, write to the Free Software
  23. //  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  24. //
  25. //=============================================================================
  26. //
  27. // OOPACK: a benchmark for comparing OOP vs. C-style programming.
  28. // 
  29. // Version: 1.7
  30. // 
  31. // Author: Arch D. Robison (robison@kai.com)
  32. //       Kuck & Associates 
  33. //       1906 Fox Dr.
  34. //       Champaign IL 61820
  35. //        
  36. // Web Info: http://www.kai.com/oopack/oopack.html
  37. //
  38. // Last revised: November 21, 1995
  39. //
  40. // This benchmark program contains a suite of tests that measure the relative 
  41. // performance of object-oriented-programming (OOP) in C++ versus just writing
  42. // plain C-style code in C++.  All of the tests are written so that a 
  43. // compiler can in principle transform the OOP code into the C-style code.  
  44. // After you run this benchmark and discover just how much you are paying to 
  45. // use object-oriented programming, you will probably say: OOP? ACK!
  46. // (Unless, of course, you have Kuck & Associates' Photon C++ compiler.)
  47. //
  48. // TO COMPILE
  49. //
  50. //    Compile with your favorite C++ compiler.  E.g. ``CC -O2 oopack.C''.
  51. //    On most machines, no special command-line options are required.  
  52. //     For Suns only, you need to define the symbol ``sun4''.  
  53. //    E.g. ``g++ -O -Dsun4 oopack.C''.
  54. //
  55. // TO RUN
  56. //
  57. //    To run the benchmark, run ``a.out Max=50000 Matrix=500 Complex=20000 Iterator=50000''.
  58. //    This runs the four tests for the specified number of iterations.
  59. //    E.g., the Max test is run for 50000 iterations.  You may want to 
  60. //    adjust the number of iterations to be small enough to get
  61. //    an answer in reasonable time, but large enough to get a reasonably
  62. //    accurate answer.
  63. //
  64. // INTERPRETING THE RESULTS
  65. //    
  66. //    Below is an example command line and the program's output.
  67. //
  68. //    $ a.out Max=5000 Matrix=50 Complex=2000  Iterator=5000
  69. //      OOPACK Version 1.7
  70. //      
  71. //      For results on various systems and compilers, examine this Web Page:
  72. //          http://www.kai.com/oopack/oopack.html
  73. //      
  74. //      Report your results by sending e-mail to oopack@kai.com.
  75. //      For a run to be accepted, adjust the number of iterations for each test
  76. //      so that each time reported is greater than 10 seconds.
  77. //      
  78. //      Send this output, along with:
  79. //      
  80. //           * your 
  81. //              + name ------------------- 
  82. //              + company/institution ---- 
  83. //      
  84. //           * the compiler
  85. //              + name ------------------- 
  86. //              + version number --------- 
  87. //              + options used ----------- 
  88. //      
  89. //           * the operating system
  90. //              + name ------------------- 
  91. //              + version number --------- 
  92. //      
  93. //           * the machine
  94. //              + manufacturer ----------- 
  95. //              + model number ----------- 
  96. //              + processor clock speed -- 
  97. //              + cache memory size ------ 
  98. //      
  99. //                                Seconds       Mflops         
  100. //    Test       Iterations     C    OOP     C    OOP  Ratio
  101. //    ----       ----------  -----------  -----------  -----
  102. //    Max              5000    1.3   1.3    3.8   4.0    1.0
  103. //    Matrix             50    1.5   2.8    8.6   4.5    1.9
  104. //    Complex          2000    1.5   5.3   10.8   3.0    3.6
  105. //    Iterator         5000    1.1   1.6    9.4   6.3    1.5
  106. //    
  107. //     The ``Test'' column gives the names of the four tests that are run.  
  108. //    The ``Iterations'' column gives the number of iterations that a test 
  109. //    was run.  The The two ``Seconds'' columns give the C-style 
  110. //    and OOP-style running times for a test.  The two ``Mflops'' columns
  111. //    give the corresponding megaflop rates.  The ``Ratio'' column gives
  112. //    the ratio between the times.  The value of 1.5 at the bottom, for 
  113. //    example, indicates that the OOP-style code for Iterator ran 1.5 times 
  114. //    more slowly than the C-style code.
  115. //
  116. //    Beware that a low ``Ratio'' could indicate either that the OOP-style
  117. //    code is compiled very well, or that the C-style code is compiled poorly.
  118. //      OOPACK performance figures for KAI's Photon C++ and some other compilers
  119. //    can be found in http://www.kai.com/oopack/oopack.html.
  120. //
  121. // Revison History
  122. //    9/17/93        Version 1.0 released
  123. //    10/5/93        Allow results to be printed even if checksums do not match.
  124. //    10/5/93        Increased ``Tolerance'' to allow 10-second runs on RS/6000.  
  125. //    10/5/93     Version 1.1 released
  126. //      1/10/94        Change author's address from Shell to KAI
  127. //    1/13/94        Added #define's for conditional compilation of individual tests
  128. //    1/21/94        Converted test functions to virtual members of class Benchmark.
  129. //     10/11/94         Added routine to inform user of command-line usage.
  130. //     10/11/94        Version 1.5 released.
  131. //     11/21/95        V1.6 Added "mail results to oopack@kai.com" message in output
  132. //     11/28/95        V1.7 Added company/institution to requested information
  133.  
  134. //=============================================================================
  135.  
  136. #include <assert.h>
  137. #include <ctype.h>
  138. #include <float.h>
  139. #include <math.h>
  140. #include <stdio.h>
  141. #include <time.h>
  142. #include <string.h>
  143. #include <stdlib.h>
  144.  
  145. //
  146. // The source-code begins with the benchmark computations themselves and
  147. // ends with code for collecting statistics.  Each benchmark ``Foo'' is
  148. // a class FooBenchmark derived from class Benchmark.  The relevant methods
  149. // are:
  150. //
  151. //    init - Initialize the input data for the benchmark
  152. //
  153. //    c_style - C-style code
  154. //
  155. //    oop_style - OOP-style code
  156. //
  157. //    check - computes number of floating-point operations and a checksum.
  158. //
  159. const int BenchmarkListMax = 4;
  160.  
  161. class Benchmark {
  162. public:
  163.     void time_both( int iteration_count ) const;
  164.     void time_one( void (Benchmark::*function)() const, int iterations, double& sec, double& Mflop, double& checksum ) const;
  165.     virtual const char * name() const = 0;
  166.     virtual void init() const = 0;
  167.     virtual void c_style() const = 0; 
  168.     virtual void oop_style() const = 0;
  169.     virtual void check( int iterations, double& flops, double& checksum ) const = 0;
  170.     static Benchmark * find( const char * name );
  171. private:
  172.     static Benchmark * list[BenchmarkListMax];
  173.     static int count;
  174. protected:
  175.     Benchmark() {list[count++] = this;}
  176. };
  177.  
  178. // The initializer for Benchmark::count *must* precede the declarations
  179. // of derived of class Benchmark.
  180. int Benchmark::count = 0;
  181. Benchmark * Benchmark::list[BenchmarkListMax];
  182.  
  183. //
  184. // The ``iterations'' argument is the number of times that the benchmark 
  185. // computation was called.  The computed checksum that ensures that the
  186. // C-style code and OOP code are computing the same result.  This 
  187. // variable also prevents really clever optimizers from removing the
  188. // the guts of the computations that otherwise would be unused.
  189. //
  190.  
  191. // Each of the following symbols must be defined to enable a test, or
  192. // undefined to disable a test.  The reason for doing this with the
  193. // preprocessor is that some compilers may choke on specific tests.
  194. #define HAVE_MAX 1
  195. #define HAVE_MATRIX 1
  196. #define HAVE_COMPLEX 1 
  197. #define HAVE_ITERATOR 1
  198.  
  199. const int N = 1000;
  200.  
  201. #if HAVE_MAX
  202. //=============================================================================
  203. //
  204. // Max benchmark
  205. //
  206. // This benchmark measures how well a C++ compiler inlines a function that 
  207. // returns the result of a comparison.  
  208. //
  209. // The functions C_Max and OOP_Max compute the maximum over a vector.
  210. // The only difference is that C_Max writes out the comparison operation
  211. // explicitly, and OOP_Max calls an inline function to do the comparison.
  212. //
  213. // This benchmark is included because some compilers do not compile 
  214. // inline functions into conditional branches as well as they might.  
  215. //
  216. const int M = 1000;        // Dimension of vector
  217. DATA U[M];            // The vector
  218. DATA MaxResult;        // Result of max computation
  219.  
  220. class MaxBenchmark: public Benchmark {
  221. private:
  222.     const char * name() const {return "Max";}
  223.     void init() const;
  224.     void c_style() const; 
  225.     void oop_style() const;
  226.     void check( int iterations, double& flops, double& checksum ) const;
  227. } TheMaxBenchmark;
  228.  
  229. void MaxBenchmark::c_style() const        // Compute max of vector (C-style)
  230. {        
  231.     DATA max = U[0];
  232.     for( int k=1; k<M; k++ )            // Loop over vector elements
  233.     if( U[k] > max )  
  234.         max=U[k];
  235.     MaxResult = max;
  236. }
  237.  
  238. inline int Greater( DATA i, DATA j ) 
  239. {
  240.     return i>j;
  241. }
  242.  
  243. void MaxBenchmark::oop_style() const         // Compute max of vector (OOP-style)
  244. {    
  245.     DATA max = U[0];
  246.     for( int k=1; k<M; k++ )            // Loop over vector elements
  247.     if( Greater( U[k], max ) ) 
  248.         max=U[k];
  249.     MaxResult = max;
  250. }
  251.  
  252. void MaxBenchmark::init() const             
  253. {
  254.     for( int k=0; k<M; k++ ) 
  255.     U[k] = k&1 ? -k : k;
  256. }
  257.  
  258. void MaxBenchmark::check( int iterations, double& flops, double& checksum ) const
  259. {
  260.     flops = (double)M*iterations;
  261.     checksum = MaxResult;
  262. }
  263. #endif /* HAVE_MAX */
  264.  
  265. #if HAVE_MATRIX
  266. //=============================================================================
  267. //
  268. // Matrix benchmark
  269. //
  270. // This benchmark measures how well a C++ compiler performs constant propagation and 
  271. // strength-reduction on classes.  C_Matrix multiplies two matrices using C-style code; 
  272. // OOP_Matrix does the same with OOP-style code.  To maximize performance on most RISC 
  273. // processors, the benchmark requires that the compiler perform strength-reduction and 
  274. // constant-propagation in order to simplify the indexing calculations in the inner loop.
  275. //
  276. const int L = 50;        // Dimension of (square) matrices.
  277.  
  278. DATA C[L*L], D[L*L], E[L*L];    // The matrices to be multiplied.
  279.  
  280. class MatrixBenchmark: public Benchmark {
  281. private:
  282.     const char * name() const {return "Matrix";}
  283.     void init() const;
  284.     void c_style() const; 
  285.     void oop_style() const;
  286.     void check( int iterations, double& flops, double& checksum ) const;
  287. } TheMatrixBenchmark;
  288.  
  289. void MatrixBenchmark::c_style() const {        // Compute E=C*D with C-style code.
  290.     for( int i=0; i<L; i++ )
  291.     for( int j=0; j<L; j++ ) {
  292.         DATA sum = 0;
  293.         for( int k=0; k<L; k++ )
  294.         sum += C[L*i+k]*D[L*k+j];
  295.         E[L*i+j] = sum;
  296.     }
  297. }
  298.  
  299. class Matrix {    // Class Matrix represents a matrix stored in row-major format (same as C).
  300. private:
  301.     DATA *data;    // Pointer to matrix data
  302. public:
  303.     int rows, cols;    // Number of rows and columns
  304.  
  305.     Matrix( int rows_, int cols_, DATA * data_ ) :
  306.     rows(rows_), cols(cols_), data(data_)
  307.     {}
  308.  
  309.     DATA& operator()( int i, int j ) {    // Access element at row i, column j
  310.     return data[cols*i+j];
  311.     }
  312. };
  313.  
  314. void MatrixBenchmark::oop_style() const {     // Compute E=C*D with OOP-style code.
  315.     Matrix c( L, L, C );            // Set up three matrices
  316.     Matrix d( L, L, D );
  317.     Matrix e( L, L, E );
  318.     for( int i=0; i<e.rows; i++ )        // Do matrix-multiplication
  319.     for( int j=0; j<e.cols; j++ ) {
  320.         DATA sum = 0;
  321.         for( int k=0; k<e.cols; k++ )
  322.         sum += c(i,k)*d(k,j);
  323.         e(i,j) = sum;
  324.     }
  325. }
  326.  
  327. void MatrixBenchmark::init() const    
  328. {
  329.     for( int j=0; j<L*L; j++ ) {
  330.     C[j] = j+1;
  331.     D[j] = 1.0/(j+1);
  332.     }
  333. }
  334.  
  335. void MatrixBenchmark::check( int iterations, double& flops, double& checksum ) const
  336. {
  337.     DATA sum = 0;
  338.     for( int k=0; k<L*L; k++ )
  339.     sum += E[k];
  340.     checksum = sum;
  341.     flops = 2.0*L*L*L*iterations;
  342. }
  343. #endif /* HAVE_MATRIX */
  344.  
  345. #if HAVE_ITERATOR
  346. //=============================================================================
  347. //
  348. // Iterator benchmark 
  349. //
  350. // Iterators are a common abstraction in object-oriented programming, which
  351. // unfortunately may incur a high cost if compiled inefficiently.
  352. // The iterator benchmark below computes a dot-product using C-style code
  353. // and OOP-style code.  All methods of the iterator are inline, and in 
  354. // principle correspond exactly to the C-style code.
  355. //
  356. // Note that the OOP-style code uses two iterators, but the C-style
  357. // code uses a single index.  Good common-subexpression elimination should,
  358. // in principle, reduce the two iterators to a single index variable, or
  359. // conversely, good strength-reduction should convert the single index into 
  360. // two iterators!  
  361. //
  362. DATA A[N];
  363. DATA B[N];
  364. DATA IteratorResult;
  365.  
  366. class IteratorBenchmark: public Benchmark {
  367. private:
  368.     const char * name() const {return "Iterator";}
  369.     void init() const;
  370.     void c_style() const; 
  371.     void oop_style() const;
  372.     void check( int iterations, double& flops, double& checksum ) const;
  373. } TheIteratorBenchmark;
  374.  
  375. void IteratorBenchmark::c_style() const         // Compute dot-product with C-style code
  376. {
  377.     DATA sum = 0;
  378.     for( int i=0; i<N; i++ )
  379.     sum += A[i]*B[i];
  380.     IteratorResult = sum;
  381. }
  382.  
  383. class Iterator {        // Iterator for iterating over array of DATA
  384. private:
  385.     int index;            // Index of current element
  386.     const int limit;        // 1 + index of last element
  387.     DATA * const array;    // Pointer to array
  388. public:
  389.     DATA look() {return array[index];}    // Get current element
  390.     void next() {index++;}            // Go to next element
  391.     int done() {return index>=limit;}        // True iff no more elements
  392.     Iterator( DATA* array1, int limit1 ) : 
  393.     array(array1), 
  394.     limit(limit1), 
  395.     index(0) 
  396.     {}
  397. };
  398.  
  399. void IteratorBenchmark::oop_style() const         // Compute dot-product with OOP-style code
  400. {
  401.     DATA sum = 0;
  402.     for( Iterator ai(A,N), bi(B,N); !ai.done(); ai.next(), bi.next() )
  403.     sum += ai.look()*bi.look();
  404.     IteratorResult = sum;
  405. }
  406.  
  407. void IteratorBenchmark::init() const    
  408. {
  409.     for( int i=0; i<N; i++ ) {
  410.     A[i] = i+1;
  411.     B[i] = 1.0/(i+1);
  412.     }
  413. }
  414.  
  415. void IteratorBenchmark::check( int iterations, double& flops, double& checksum ) const {
  416.     flops = 2*N*iterations;
  417.     checksum = IteratorResult;
  418. }
  419. #endif /* HAVE_ITERATOR */
  420.  
  421. #if HAVE_COMPLEX
  422. //=============================================================================
  423. //
  424. // Complex benchmark
  425. //
  426. // Complex numbers are a common abstraction in scientific programming.
  427. // This benchmark measures how fast they are in C++ relative to the same
  428. // calculation done by explicitly writing out the real and imaginary parts.
  429. // The calculation is a complex-valued ``SAXPY'' operation.
  430. //
  431. // The complex arithmetic is all inlined, so in principle the code should
  432. // run as fast as the version using explicit real and imaginary parts.
  433. //
  434. class ComplexBenchmark: public Benchmark {
  435. private:
  436.     const char * name() const {return "Complex";}
  437.     void init() const;
  438.     void c_style() const; 
  439.     void oop_style() const;
  440.     void check( int iterations, double& flops, double& checksum ) const;
  441. } TheComplexBenchmark;
  442.  
  443. class Complex {
  444. public:
  445.     double re, im;
  446.     Complex( double r, double i ) : re(r), im(i) {}
  447.     Complex() {}
  448. };
  449.  
  450. inline Complex operator+( Complex a, Complex b )     // Complex add
  451. {
  452.     return Complex( a.re+b.re, a.im+b.im );
  453. }
  454.  
  455. inline Complex operator*( Complex a, Complex b )     // Complex multiply
  456. {
  457.     return Complex( a.re*b.re-a.im*b.im, a.re*b.im+a.im*b.re );
  458. }
  459.  
  460. Complex X[N], Y[N];                // Arrays used by benchmark
  461.  
  462. void ComplexBenchmark::c_style() const         // C-style complex-valued SAXPY operation
  463. {
  464.     double factor_re = 0.5;
  465.     double factor_im = 0.86602540378443864676;
  466.     for( int k=0; k<N; k++ ) {
  467.     Y[k].re = Y[k].re + factor_re*X[k].re - factor_im*X[k].im;
  468.     Y[k].im = Y[k].im + factor_re*X[k].im + factor_im*X[k].re;
  469.     }
  470. }
  471.  
  472. void ComplexBenchmark::oop_style() const     // OOP-style complex-valued SAXPY operation 
  473. {
  474.     Complex factor( 0.5, 0.86602540378443864676 );
  475.     for( int k=0; k<N; k++ )
  476.     Y[k] = Y[k] + factor*X[k];
  477. }
  478.  
  479. void ComplexBenchmark::init() const    
  480. {
  481.     for( int k=0; k<N; k++ ) {
  482.     X[k] = Complex( k+1, 1.0/(k+1) );
  483.     Y[k] = Complex( 0, 0 );
  484.     }
  485. }
  486.  
  487. void ComplexBenchmark::check( int iterations, double& flops, double& checksum ) const {
  488.     double sum = 0;
  489.     for( int k=0; k<N; k++ )
  490.     sum += Y[k].re + Y[k].im;
  491.     checksum = sum;
  492.     flops = 8*N*iterations;
  493. }
  494. #endif /* HAVE_COMPLEX */
  495.  
  496. //=============================================================================
  497. // End of benchmark computations.  
  498. //=============================================================================
  499.  
  500. // All the code below is for running and timing the benchmarks.                             
  501. #if defined(sun4) && !defined(CLOCKS_PER_SEC)
  502. // Sun/4 include-files seem to be missing CLOCKS_PER_SEC.
  503. #define CLOCKS_PER_SEC 1000000    
  504. #endif
  505.  
  506. //
  507. // TimeOne
  508. //
  509. // Time a single benchmark computation.
  510. //
  511. // Inputs
  512. //    function = pointer to function to be run and timed.
  513. //    iterations = number of times to call function.
  514. //
  515. // Outputs
  516. //    sec = Total number of seconds for calls of function.
  517. //    Mflop = Megaflop rate of function.
  518. //    checksum = checksum computed by function.
  519. //     
  520. void Benchmark::time_one( void (Benchmark::*function)() const, int iterations, double& sec, double& Mflop, double& checksum ) const
  521. {
  522.     // Initialize and run code once to load caches
  523.     init();
  524.     (this->*function)();
  525.  
  526.     // Initialize and run code.
  527.     init();
  528.     clock_t t0 = clock();
  529.     for( int k=0; k<iterations; k++ ) 
  530.         (this->*function)();
  531.     clock_t t1 = clock();
  532.  
  533.     // Update checksum and compute number of floating-point operations.
  534.     double flops;
  535.     check( iterations, flops, checksum );
  536.  
  537.     sec = (t1-t0) / (double)CLOCKS_PER_SEC;
  538.     Mflop = flops/sec*1e-6;
  539.  
  540. }
  541.  
  542. //
  543. // The variable ``C_Seconds'' is the time in seconds in which to run the 
  544. // C-style benchmarks.
  545. //
  546. double C_Seconds = 1;    
  547.  
  548. //
  549. // The variable ``Tolerance'' is the maximum allowed relative difference 
  550. // between the C and OOP checksums.  Machines with multiply-add 
  551. // instructions may produce different answers when they use those 
  552. // instructions rather than separate instructions.
  553. //
  554. // There is nothing magic about the 32, it's just the result of tweaking.
  555. //
  556. const double Tolerance = 64*DBL_EPSILON;
  557.  
  558. Benchmark * Benchmark::find( const char * name ) {
  559.     for( int i=0; i<count; i++ )
  560.     if( strcmp( name, list[i]->name() )== 0 )
  561.         return list[i];
  562.     return NULL;    
  563. }
  564.  
  565. //
  566. // Benchmark::time_both
  567. //
  568. // Runs the C and Oop versions of a benchmark computation, and print the 
  569. // results.
  570. //
  571. // Inputs
  572. //    name = name of the benchmark
  573. //    c_style = benchmark written in C-style code
  574. //    oop_style = benchmark written in OOP-style code
  575. //    check = routine to compute checksum on answer
  576. //
  577. void Benchmark::time_both( int iterations ) const {
  578.     // Run the C-style code. 
  579.     double c_sec, c_Mflop, c_checksum;
  580.     time_one( &Benchmark::c_style, iterations, c_sec, c_Mflop, c_checksum );
  581.    
  582.     // Run the OOP-style code. 
  583.     double oop_sec, oop_Mflop, oop_checksum;
  584.     time_one( &Benchmark::oop_style, iterations, oop_sec, oop_Mflop, oop_checksum );
  585.  
  586.     // Compute execution-time ratio of OOP to C.  This is also the 
  587.     // reciprocal of the Megaflop ratios.                                
  588.     double ratio = oop_sec/c_sec;
  589.  
  590.     // Compute the absolute and relative differences between the checksums
  591.     // for the two codes.
  592.     double diff = c_checksum - oop_checksum;
  593.     double min = c_checksum < oop_checksum ? c_checksum : oop_checksum;
  594.     double rel = diff/min;
  595.  
  596.     // If the relative difference exceeds the tolerance, print an error-message,
  597.     // otherwise print the statistics.
  598.     if( rel > Tolerance || rel < -Tolerance ) {
  599.     printf( "%-10s: warning: relative checksum error of %g between C (%g) and oop (%g)\n",
  600.             name(), rel, c_checksum, oop_checksum );
  601.     } 
  602.     printf( "%-10s %10d  %5.1f %5.1f  %5.1f %5.1f  %5.1f\n", 
  603.         name(), iterations, c_sec, oop_sec, c_Mflop, oop_Mflop, ratio );
  604. }
  605.  
  606. const char * Version = "Version 1.7"; // The OOPACK version number 
  607.  
  608. void Usage( int /*argc*/, char * argv[] ) {
  609.     printf( "Usage:\t%s test1=iterations1 test2=iterations2 ...\n", argv[0] ); 
  610.     printf( "E.g.:\ta.out  Max=5000 Matrix=50 Complex=2000  Iterator=5000\n" );
  611.     exit(1);
  612. }
  613.  
  614. int main( int argc, char * argv[] ) 
  615. {
  616.     // The available benchmarks are automatically put into the list of available benchmarks
  617.     // by the constructor for Benchmark.
  618.  
  619.     // Check if user does not know command-line format.
  620.     if( argc==1 ) {
  621.     Usage( argc, argv );
  622.     }
  623.     int i;
  624.     for( i=1; i<argc; i++ ) {
  625.     if( !isalpha(argv[i][0]) )
  626.         Usage( argc, argv );
  627.     }
  628.  
  629.     // Print the request for results
  630.     printf("\n");
  631.     printf("OOPACK %s\n",Version);
  632.     printf("\n");
  633.     printf("For results on various systems and compilers, examine this Web Page:\n");
  634.     printf("    http://www.kai.com/oopack/oopack.html\n");
  635.     printf("\n");
  636.     printf("Report your results by sending e-mail to oopack@kai.com.\n");
  637.     printf("For a run to be accepted, adjust the number of iterations for each test\n");
  638.     printf("so that each time reported is greater than 10 seconds.\n");
  639.     printf("\n");
  640.     printf("Send this output, along with:\n");
  641.     printf("\n");
  642.     printf("     * your\n");
  643.     printf("        + name ------------------- \n");
  644.     printf("        + company/institution ---- \n");
  645.     printf("\n");
  646.     printf("     * the compiler\n");
  647.     printf("        + name ------------------- \n");
  648.     printf("        + version number --------- \n");
  649.     printf("        + options used ----------- \n");
  650.     printf("\n");
  651.     printf("     * the operating system\n");
  652.     printf("        + name ------------------- \n");
  653.     printf("        + version number --------- \n");
  654.     printf("\n");
  655.     printf("     * the machine\n");
  656.     printf("        + manufacturer ----------- \n");
  657.     printf("        + model number ----------- \n");
  658.     printf("        + processor clock speed -- \n");
  659.     printf("        + cache memory size ------ \n");
  660.     printf("\n");
  661.  
  662.     // Print header.
  663.     printf("%-10s %10s  %11s  %11s  %5s\n", "", "", "Seconds  ", "Mflops  ", "" );
  664.     printf("%-10s %10s  %5s %5s  %5s %5s  %5s\n",
  665.        "Test", "Iterations", " C ", "OOP", " C ", "OOP", "Ratio" );
  666.     printf("%-10s %10s  %11s  %11s  %5s\n", "----", "----------", "-----------", "-----------", "-----" );
  667.  
  668.     for( i=1; i<argc; i++ ) {
  669.     const char * test_name = strtok( argv[i], "=" );
  670.     const char * rhs =  strtok( NULL, "" );
  671.     if( rhs==NULL ) {
  672.         printf("missing iteration count for test '%s'\n", test_name );
  673.     } else {
  674.         int test_count = (int)strtol( rhs, 0, 0 );
  675.         Benchmark * b = Benchmark::find( test_name );
  676.         if( b==NULL ) {
  677.         printf("skipping non-existent test = '%s'\n", test_name );
  678.         } else {
  679.         b->time_both( test_count );
  680.         }
  681.     }
  682.     }
  683.  
  684.     /* Print blank line. */
  685.     printf("\n");
  686.  
  687.     return 0;
  688. }
  689.